package com.restkeeper.store.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.restkeeper.exception.BussinessException;
import com.restkeeper.store.dto.CreditDTO;
import com.restkeeper.store.entity.Credit;
import com.restkeeper.store.entity.CreditCompanyUser;
import com.restkeeper.store.mapper.CreditMapper;
import com.restkeeper.utils.SystemCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 挂账单位管理表 服务实现类
 * </p>
 */
@Slf4j
@Component
@Service(version = "1.0.0",protocol = "dubbo")
public class CreditServiceImpl extends ServiceImpl<CreditMapper, Credit> implements ICreditService {

    @Autowired
    private ICreditCompanyUserService creditCompanyUserService;

    /**
     * 分页查询挂账列表信息
     * @param pageNo
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public IPage<CreditDTO> queryPageByName(long pageNo, long pageSize, String name) {

        // 构建分页条件
        IPage<Credit> page = new Page<Credit>(pageNo, pageSize);
        // 构建查询条件
        LambdaQueryWrapper<Credit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(name), Credit::getUserName, name)
                .or()
                .inSql(StringUtils.isNotBlank(name), Credit::getCreditId,
                        "select credit_id from t_credit_company_user where user_name like '%"
                                + StringEscapeUtils.escapeSql(name) + "%'");
        queryWrapper.orderByAsc(Credit::getLastUpdateTime);
        this.page(page, queryWrapper);

        // 处理返回数据
        IPage<CreditDTO> creditDTOIPage = new Page<>();

        // 进行对象拷贝 copyProperties(源对象，目标对象，可忽略属性)，不拷贝records属性
        BeanUtils.copyProperties(page, creditDTOIPage, "records");

        // 挂账类型为公司的话，需要查找出旗下的挂账人列表信息
        List<Credit> creditList = page.getRecords();
        List<CreditDTO> creditDTOList = new ArrayList<>();
        if(creditList != null) {
            creditDTOList = creditList.stream().map( c -> {

                CreditDTO creditDTO = new CreditDTO();
                // 进行对象拷贝
                BeanUtils.copyProperties(c, creditDTO);
                // 查找挂账类型为公司的对应挂账人信息
                if (c.getCreditType() == SystemCode.CREDIT_TYPE_COMPANY) {
                    LambdaQueryWrapper<CreditCompanyUser> queryWrapper2 = new LambdaQueryWrapper<>();
                    queryWrapper2.eq(CreditCompanyUser::getCreditId, c.getCreditId());
                    List<CreditCompanyUser> companyUserList = creditCompanyUserService.list(queryWrapper2);
                    creditDTO.setUsers(companyUserList);
                }
                return creditDTO;
            }).collect(Collectors.toList());
        }
        creditDTOIPage.setRecords(creditDTOList);

        return creditDTOIPage;
    }

    /**
     * 根据id查询挂账详情
     * @param id
     * @return
     */
    @Override
    public CreditDTO getCreditById(String id) {

        // 根据id获取挂账信息
        Credit credit = this.getById(id);
        if(credit == null){
            throw new BussinessException("该挂账信息不存在");
        }

        CreditDTO creditDTO = new CreditDTO();
        // 进行对象拷贝
        BeanUtils.copyProperties(credit, creditDTO);

        // creditDTO.setUserName("测试");
        // creditDTO.setPhone("12345678900");

        // 若该挂账类型为公司，则还需要查询该公司的挂账人列表
        if (credit.getCreditType() == SystemCode.CREDIT_TYPE_COMPANY) {
            LambdaQueryWrapper<CreditCompanyUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CreditCompanyUser::getCreditId, credit.getCreditId());
            List<CreditCompanyUser> companyUserList = creditCompanyUserService.list(queryWrapper);

            creditDTO.setUsers(companyUserList);
        }

        return creditDTO;
    }

    /**
     * 新增挂账
     *
     * @param credit
     * @param companyUserList
     * @return
     */
    @Override
    @Transactional
    public boolean addCredit(Credit credit, List<CreditCompanyUser> companyUserList) {

        // 保存挂账主体信息
        this.save(credit);

        // 保存挂账类型为公司的挂账人信息
        if (companyUserList != null && !companyUserList.isEmpty()){

            // 获取用户名列表
            List<String> userNameList = companyUserList.stream().map(u -> u.getUserName())
                    .collect(Collectors.toList());

            // 去重判断
            long count = userNameList.stream().distinct().count();
            if (userNameList.size() != count){
                throw new BussinessException("用户名重复");
            }

            // 为挂账人信息设置关联的挂账id
            companyUserList.forEach(u -> u.setCreditId(credit.getCreditId()));

            // 批量保存挂账人信息
            return creditCompanyUserService.saveBatch(companyUserList);
        }

        return true;
    }

    /**
     * 修改挂账
     * @param credit
     * @param companyUserList
     * @return
     */
    @Override
    @Transactional
    public boolean updateCredit(Credit credit, List<CreditCompanyUser> companyUserList) {

        // 删除挂账类型为公司的原挂账人信息
        if (credit.getCreditType() == SystemCode.CREDIT_TYPE_COMPANY){
            LambdaQueryWrapper<CreditCompanyUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CreditCompanyUser::getCreditId, credit.getCreditId());
            creditCompanyUserService.remove(queryWrapper);
        }

        // 保存挂账人信息
        if(companyUserList != null && !companyUserList.isEmpty()){

            // 获取用户名列表
            List<String> userNameList = companyUserList.stream().map(u -> u.getUserName()).collect(Collectors.toList());

            // 去重判断
            long count = userNameList.stream().distinct().count();
            if(userNameList.size() != count){
                throw new BussinessException("用户名重复");
            }

            // 为挂账人信息设置关联的挂账id
            companyUserList.forEach(u -> u.setCreditId(credit.getCreditId()));

            // 批量保存挂账人信息
            return creditCompanyUserService.saveBatch(companyUserList);
        }

        // 修改挂账主体信息
        return this.saveOrUpdate(credit);
    }

    /**
     * 挂账数据导出
     * @param creditId
     * @param start
     * @param end
     * @return
     */
    @Override
    public boolean export(String creditId, Date start, Date end) {


        return false;
    }
}
